import type {
  DepartmentSet,
  PwdChange,
  UserInfo,
  UserList,
  UserLogin,
  UserRegister,
  UserUpdateAdmin,
  UserUpdateCurrent,
} from '~/types/user'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import {
  changePassword,
  getAllUsers,
  getUserById,
  refreshToken,
  resetUserPassword,
  setUserDepartment,
  updateCurrentUser,
  updateUserAdmin,
  userLogin,
  userRegister,
} from '~/api/user'

export const useUserStore = defineStore('user', () => {
  // State
  const user = ref<UserInfo | null>(null)
  const token = ref<string | null>(null)
  const refreshTokenValue = ref<string | null>(null)

  // Getters
  const isAuthenticated = computed(() => !!token.value)
  const currentUser = computed(() => user.value)
  const authToken = computed(() => token.value)
  const userRole = computed(() => user.value?.role || null)

  // Actions
  const logout = () => {
    user.value = null
    token.value = null
    refreshTokenValue.value = null
  }

  const login = async (credentials: UserLogin) => {
    const response = await userLogin(credentials)

    token.value = response.token
    refreshTokenValue.value = response.refreshToken
    user.value = response.user
  }

  const register = async (userData: UserRegister) => {
    await userRegister(userData)
    await login({
      username: userData.username,
      password: userData.password,
    })
  }

  const updateProfile = async (userData: UserUpdateCurrent) => {
    user.value = await updateCurrentUser(userData)
  }

  const updatePassword = async (passwordData: PwdChange) => {
    await changePassword(passwordData)
  }

  const refreshAuthToken = async () => {
    if (!refreshTokenValue.value) {
      throw new Error('No refresh token available')
    }
    const { token: newToken } = await refreshToken(refreshTokenValue.value)
    token.value = newToken
  }

  // Admin actions
  const fetchUserList = async (): Promise<UserList> => {
    return await getAllUsers()
  }

  const fetchUser = async (id: number): Promise<UserInfo> => {
    return await getUserById(id)
  }

  const updateUser = async (id: number, data: UserUpdateAdmin): Promise<UserInfo> => {
    return await updateUserAdmin(id, data)
  }

  const resetPassword = async (id: number): Promise<{ message: string }> => {
    return await resetUserPassword(id)
  }

  const assignDepartment = async (id: number, data: DepartmentSet): Promise<UserInfo> => {
    return await setUserDepartment(id, data)
  }

  return {
    // State
    user,
    token,
    refreshToken: refreshTokenValue,

    // Getters
    isAuthenticated,
    currentUser,
    authToken,
    userRole,

    // User actions
    login,
    register,
    logout,
    updateProfile,
    updatePassword,
    refreshAuthToken,

    // Admin actions
    fetchUserList,
    fetchUser,
    updateUser,
    resetPassword,
    assignDepartment,
  }
}, {
  persist: {
    key: 'userinfo',
    pick: ['user', 'token', 'refreshToken'],
  },
})
